import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import axios from 'axios';
import { MiniProgramConfig } from './entities/miniprogram-config.entity';
import { MiniProgramSession } from './entities/miniprogram-session.entity';
import { WxLoginRequestDto, WxLoginResponseDto, PaginationDto } from './dto';

@Injectable()
export class MiniProgramService {
  constructor(
    @InjectRepository(MiniProgramConfig)
    private configRepository: Repository<MiniProgramConfig>,
    @InjectRepository(MiniProgramSession)
    private sessionRepository: Repository<MiniProgramSession>,
    private configService: ConfigService,
    private jwtService: JwtService,
  ) { }

  async login(loginDto: WxLoginRequestDto): Promise<WxLoginResponseDto> {
    const { code } = loginDto;

    // 获取小程序配置
    const config = await this.getConfig();

    try {
      // 调用微信API获取openid和session_key
      const wxResponse = await axios.get('https://api.weixin.qq.com/sns/jscode2session', {
        params: {
          appid: config.appId,
          secret: config.secret,
          js_code: code,
          grant_type: 'authorization_code',
        },
      });

      const { openid, session_key, unionid } = wxResponse.data;

      if (!openid) {
        throw new BadRequestException('微信登录失败');
      }

      // 查找或创建用户
      let user = await this.findOrCreateUser(openid, unionid);

      // 创建或更新会话
      const session = await this.createOrUpdateSession(user.id, openid, unionid, session_key);

      // 生成JWT令牌
      const payload = {
        sub: user.id,
        openid,
        unionid,
        sessionId: session.id
      };

      const accessToken = this.jwtService.sign(payload);
      const expiresIn = 7 * 24 * 60 * 60; // 7天

      // 更新会话的访问令牌
      session.accessToken = accessToken;
      session.expiresAt = new Date(Date.now() + expiresIn * 1000);
      await this.sessionRepository.save(session);

      return {
        accessToken,
        tokenType: 'Bearer',
        expiresIn,
        userInfo: {
          id: user.id,
          username: user.username,
          nickname: user.nickname,
          avatar: user.avatar,
          openid,
          unionid,
        },
      };
    } catch (error) {
      throw new BadRequestException('微信登录失败: ' + error.message);
    }
  }

  async getConfig(): Promise<MiniProgramConfig> {
    const config = await this.configRepository.findOne({ where: { status: 1 } });
    if (!config) {
      throw new NotFoundException('小程序配置不存在');
    }
    return config;
  }

  async getUserInfo(openid: string) {
    const session = await this.sessionRepository.findOne({
      where: { openid, status: 1 },
      relations: ['user']
    });

    if (!session) {
      throw new NotFoundException('用户会话不存在');
    }

    return {
      code: 200,
      message: '获取用户信息成功',
      data: session.user,
      timestamp: Date.now(),
    };
  }

  async updateUserInfo(userInfo: any) {
    // 这里应该调用用户服务更新用户信息
    return {
      code: 200,
      message: '更新用户信息成功',
      data: userInfo,
      timestamp: Date.now(),
    };
  }

  async getPhoneNumber(data: { code: string; encryptedData: string; iv: string }) {
    // 这里应该调用微信API解密手机号
    return {
      code: 200,
      message: '获取手机号成功',
      data: { phone: '138****8888' },
      timestamp: Date.now(),
    };
  }

  async getSessions(paginationDto: PaginationDto) {
    const { page = 1, limit = 10 } = paginationDto;
    const skip = (page - 1) * limit;

    const [sessions, total] = await this.sessionRepository.findAndCount({
      skip,
      take: limit,
      order: { createdAt: 'DESC' },
    });

    return {
      code: 200,
      message: '获取会话列表成功',
      data: {
        sessions,
        meta: {
          page,
          limit,
          total,
          totalPages: Math.ceil(total / limit),
        },
      },
      timestamp: Date.now(),
    };
  }

  async getSession(id: number) {
    const session = await this.sessionRepository.findOne({ where: { id } });
    if (!session) {
      throw new NotFoundException('会话不存在');
    }

    return {
      code: 200,
      message: '获取会话详情成功',
      data: session,
      timestamp: Date.now(),
    };
  }

  private async findOrCreateUser(openid: string, unionid?: string) {
    // 这里应该调用用户服务查找或创建用户
    // 暂时返回模拟数据
    return {
      id: 1,
      username: `wx_${openid.substring(0, 8)}`,
      nickname: '微信用户',
      avatar: '',
      openid,
      unionid,
    };
  }

  private async createOrUpdateSession(
    userId: number,
    openid: string,
    unionid: string,
    sessionKey: string
  ): Promise<MiniProgramSession> {
    let session = await this.sessionRepository.findOne({
      where: { openid, status: 1 }
    });

    if (session) {
      // 更新现有会话
      session.sessionKey = sessionKey;
      session.unionid = unionid;
      session.updatedAt = new Date();
    } else {
      // 创建新会话
      session = this.sessionRepository.create({
        userId,
        openid,
        unionid,
        sessionKey,
        accessToken: '',
        expiresAt: new Date(),
        status: 1,
      });
    }

    return this.sessionRepository.save(session);
  }
}
